@file:Suppress("FunctionName")

package com.lokiy.core.adapter

import android.app.Activity
import android.app.Application
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.*
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import com.lokiy.core.ext.inflateMethod

/**
 *
 * @author Lokiy
 * @date 2023-02-17 下午3:51
 */


/**
 * LifecycleViewBindingAdapter
 *
 *    val adapter = LifecycleViewBindingAdapter<String, FragmentItem1Binding> { holder, item ->
 *        holder.binding.text.text = item
 *        liveData.observe(holder) {
 *            holder.binding.text.text = it.toString()
 *        }
 *    }
 */
inline fun <T, reified Binding : ViewBinding> LifecycleViewBindingAdapter(
    pageSize: Int = 20,
    noinline onLoadMore: () -> Unit = {},
    noinline onViewRecycled: (LifecycleBindingHolder<Binding>) -> Unit = {},
    noinline onBindHolder: LifecycleViewBindingAdapter<T, Binding>.(LifecycleBindingHolder<Binding>, T) -> Unit,
) = object : LifecycleLoadMoreAdapter<T, Binding>(pageSize, onLoadMore, onViewRecycled, onBindHolder){}

/**
 * MixLifecycleViewBindingAdapter
 *
 * @see [MixViewBindingAdapter]
 */
fun MixLifecycleViewBindingAdapter(
    pageSize: Int = 20,
    onLoadMore: () -> Unit = {},
    onViewRecycled: (LifecycleBindingHolder<ViewBinding>) -> Unit = {},
    onBindHolder: LifecycleViewBindingAdapter<com.lokiy.adapter.BindingItem, ViewBinding>.(LifecycleBindingHolder<ViewBinding>, com.lokiy.adapter.BindingItem) -> Unit,
) = LifecycleLoadMoreAdapter(pageSize, onLoadMore, onViewRecycled, onBindHolder)











/**
 * LifecycleViewBindingAdapter
 * holder包含LifecycleOwner
 */
abstract class LifecycleViewBindingAdapter<T, Binding : ViewBinding> : com.lokiy.adapter.ViewBindingAdapter<T, Binding, LifecycleBindingHolder<Binding>>() {

    private lateinit var appCompatActivity: AppCompatActivity
    private val activityLifecycleLiveData: MutableLiveData<Lifecycle.State> = MutableLiveData(Lifecycle.State.RESUMED)
    private val lifecycleCallbacks = ActivityLifecycleCallbacks(activityLifecycleLiveData)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LifecycleBindingHolder<Binding> {
        return LifecycleBindingHolder(typeArray.get(viewType).inflateMethod.invoke(this, LayoutInflater.from(parent.context), parent, false) as Binding)
    }

    override fun onBindViewHolder(holder: LifecycleBindingHolder<Binding>, position: Int) {
        holder.onAppear()
        activityLifecycleLiveData.observeForever(HolderObserve(holder, activityLifecycleLiveData))
        super.onBindViewHolder(holder, position)
    }

    final override fun onBindViewHolder(holder: com.lokiy.adapter.BindingHolder<Binding>, item: T?) {
        onBindViewHolder(holder as LifecycleBindingHolder<Binding>, item)
    }

    abstract fun onBindViewHolder(holder: LifecycleBindingHolder<Binding>, item: T?)

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        super.onAttachedToRecyclerView(recyclerView)
        appCompatActivity = recyclerView.context as AppCompatActivity
        appCompatActivity.application.registerActivityLifecycleCallbacks(lifecycleCallbacks)
        lifecycleCallbacks.appCompatActivity = appCompatActivity
    }

    override fun onViewDetachedFromWindow(holder: LifecycleBindingHolder<Binding>) {
        super.onViewDetachedFromWindow(holder)
        holder.onDestroy()
    }
}

/**
 * LifecycleBindingHolder
 */
class LifecycleBindingHolder<Binding : ViewBinding>(binding: Binding) : com.lokiy.adapter.BindingHolder<Binding>(binding), LifecycleOwner {
    private val lifecycleRegistry = LifecycleRegistry(this)

    init {
        lifecycleRegistry.currentState = Lifecycle.State.INITIALIZED
        lifecycleRegistry.currentState = Lifecycle.State.CREATED
        lifecycleRegistry.currentState = Lifecycle.State.STARTED
    }

    fun onAppear() {
        lifecycleRegistry.currentState = Lifecycle.State.RESUMED
    }

    fun onDisappear() {
        lifecycleRegistry.currentState = Lifecycle.State.STARTED
    }

    fun onDestroy() {
        lifecycleRegistry.currentState = Lifecycle.State.CREATED
        lifecycleRegistry.currentState = Lifecycle.State.DESTROYED
    }

    override fun getLifecycle(): Lifecycle {
        return lifecycleRegistry
    }
}

/**
 * ActivityLifecycleCallbacks
 */
private class ActivityLifecycleCallbacks(val activityLifecycleLiveData: MutableLiveData<Lifecycle.State>) : Application.ActivityLifecycleCallbacks {
    lateinit var appCompatActivity: AppCompatActivity
    override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
        activityLifecycleLiveData.value = Lifecycle.State.INITIALIZED
        activityLifecycleLiveData.value = Lifecycle.State.CREATED
    }

    override fun onActivityStarted(activity: Activity) {
        activityLifecycleLiveData.value = Lifecycle.State.STARTED
    }

    override fun onActivityResumed(activity: Activity) {
        activityLifecycleLiveData.value = Lifecycle.State.RESUMED
    }

    override fun onActivityPaused(activity: Activity) {
        activityLifecycleLiveData.value = Lifecycle.State.STARTED
    }

    override fun onActivityStopped(activity: Activity) {
        activityLifecycleLiveData.value = Lifecycle.State.CREATED
    }

    override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
    }

    override fun onActivityDestroyed(activity: Activity) {
        activityLifecycleLiveData.value = Lifecycle.State.DESTROYED
        if (this::appCompatActivity.isInitialized) {
            appCompatActivity.application.unregisterActivityLifecycleCallbacks(this)
        }
    }

}

/**
 * HolderObserve
 */
private class HolderObserve(val holder: LifecycleBindingHolder<*>, val liveData: LiveData<Lifecycle.State>) : Observer<Lifecycle.State> {
    override fun onChanged(it: Lifecycle.State?) {
        when (it ?: return) {
            Lifecycle.State.RESUMED -> {
                holder.onAppear()
            }
            Lifecycle.State.INITIALIZED -> {
            }
            Lifecycle.State.DESTROYED -> {
                holder.onDestroy()
                liveData.removeObserver(this)
            }
            Lifecycle.State.STARTED, Lifecycle.State.CREATED -> {
                holder.onDisappear()
            }
        }
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as HolderObserve

        if (holder != other.holder) return false

        return true
    }

    override fun hashCode(): Int {
        return holder.hashCode()
    }

}